package types

import (
	"errors"
	"fmt"

	"gopkg.in/src-d/go-git.v4/plumbing"
	"gopkg.in/src-d/go-git.v4/plumbing/format/packfile"
)

var (
	// ErrorNoFind can not find object in pack file
	ErrorNoFind = errors.New("No Find")
)

// Geter get object by hash
type Geter interface {
	Hiter
	Get(Selector) ([]byte, plumbing.ObjectType, *Header32, error)
}

// SomeGeter some geter
type SomeGeter []Geter

// Get inferace implement
func (gs SomeGeter) Get(s Selector) (body []byte, t plumbing.ObjectType, h *Header32, err error) {
	err = ErrorNoFind
	for _, g := range gs {
		var hash Hash
		hash, err = Selector2Hash(s)
		if err != nil {
			return
		}
		if g.Hit(hash) {
			body, t, h, err = g.Get(s)
			if err == ErrorNoFind {
				continue
			}
			return
		}
	}
	return
}

// Hit interface
func (gs SomeGeter) Hit(h Hash) bool {
	for _, g := range gs {
		if g.Hit(h) {
			return true
		}
	}
	return false
}

// ResolveObj resolve obj
func ResolveObj(gs Geter, s Selector) (body []byte, t plumbing.ObjectType, err error) {
	var base []byte
	var bh *Header32
	body, t, bh, err = gs.Get(s)
	if bh == nil {
		return
	}
	if err != nil {
		return
	}
	base, t, err = ResolveObj(gs, FullSelect(bh.ToHash256()))
	if err != nil {
		fmt.Println("delta ", err, bh.Hash.String(), bh.Size)
		return
	}

	body, err = packfile.PatchDelta(base, body)
	return
}
